<?php


namespace App\Exception\Handler;

use App\Constants\ErrorCode;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\Validation\ValidationException;
use Psr\Http\Message\ResponseInterface;
use App\Exception\BusinessException;
use Psr\Container\ContainerInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
use Throwable;

class HttpErrExceptionHandler extends ExceptionHandler
{

    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var StdoutLoggerInterface
     */
    protected $logger;


    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->logger = $container->get(StdoutLoggerInterface::class);
    }


    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        if ($throwable instanceof ValidationException) {

            $messages = $throwable->validator->errors()->all();
            // 格式化输出
            $data = json_encode([
                'code' => ErrorCode::SYSTEM_INVALID,
                'msg' => $messages,
                'data' => [],
            ], JSON_UNESCAPED_UNICODE);
            // 阻止异常冒泡
            $this->stopPropagation();
            return $response->withHeader("Content-Type", "application/json;charset=utf-8")->withStatus(200)->withBody(new SwooleStream($data));
        }

        // 判断被捕获到的异常是希望被捕获的异常
        if ($throwable instanceof BusinessException) {
            // 格式化输出
            $data = json_encode([
                'code' => $throwable->getCode(),
                'msg' => $throwable->getMessage(),
                'data' => [],
            ], JSON_UNESCAPED_UNICODE);
            $this->logger->warning($this->container->get(FormatterInterface::class)->format($throwable));
            // 阻止异常冒泡
            $this->stopPropagation();
            return $response->withHeader("Content-Type", "application/json;charset=utf-8")->withStatus(200)->withBody(new SwooleStream($data));
        }
        // 交给下一个异常处理器
        return $response;

        // 或者不做处理直接屏蔽异常
    }

    /**
     * 判断该异常处理器是否要对该异常进行处理
     */
    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}